package io.mft.commons.multithreading.worker;

import java.io.File;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import cn.hutool.core.io.FileUtil;



/**
 * 线程池管理
 * @说明：TODO
 * @类型名称：ThreadPoolManager
 * @创建者: 胡常建  
 * @创建时间: 2018年12月19日 上午11:20:57
 * @修改者: 胡常建  
 * @修改时间: 2018年12月19日 上午11:20:57
 */
public class ThreadPoolManager
{
	static Logger logger=LoggerFactory.getLogger(ThreadPoolManager.class);

	

    /**
     * 线程池集合
     */
    private static final Map<String, ThreadPoolTaskExecutor> POOLMAP = new ConcurrentHashMap<String, ThreadPoolTaskExecutor>();
   // private static final Map<ClassLoader,  Map<String, ThreadPoolTaskExecutor>> classLoaderPool=new ConcurrentHashMap<ClassLoader, Map<String,ThreadPoolTaskExecutor>>();
	static Runnable printer=new Runnable() {
		
		
		private File threadPoolStatusFile() {
			try {
				URL url=ThreadPoolManager.class.getClassLoader().getResource(".");
				File file=new File(url.getFile());
				file=file.getParentFile();
				String threadPoolStatusDir=file.getPath()+File.separator+"stat"+File.separator+"threadPool";
				File dir=new File(threadPoolStatusDir);
				dir.mkdirs();
				String threadPoolStatusPath=threadPoolStatusDir+File.separator+"status.txt";
				File statusFile=new File(threadPoolStatusPath);
				if (!statusFile.exists()) {
					statusFile.createNewFile();
				}
				return statusFile;
			} catch (Exception e) {
				logger.error("",e);
				return null;
			}

		}
		@Override
		public void run() {
			File threadPoolStatusFile=threadPoolStatusFile();
			while (true) {
				try {
					TimeUnit.SECONDS.sleep(10);
					/**
					 * 线程编号 当前线程数 最大线程数 可用任务队列容量 待处理任务数 计划执行任务数 活动线程数 执行完成任务数
					 */
					StringBuffer info=new StringBuffer();
						info.append("线程池状态:\n");
					POOLMAP.entrySet().forEach(p->{
						ThreadPoolTaskExecutor pool=p.getValue();
		  info.append(String.format("线程池编号:%s 当前线程数:%s 最大线程数:%s 可用任务队列容量:%s 待处理任务数:%s 计划执行任务数:%s 活动线程数:%s 执行完成任务数:%s          \n",p.getKey(),pool.getPoolSize(),pool.getThreadPoolExecutor().getMaximumPoolSize(),pool.getThreadPoolExecutor().getQueue().remainingCapacity(),pool.getThreadPoolExecutor().getQueue().size(),pool.getThreadPoolExecutor().getTaskCount(),pool.getActiveCount(),pool.getThreadPoolExecutor().getCompletedTaskCount()));     
					});
					if (threadPoolStatusFile!=null) {
						FileUtil.writeUtf8String(info.toString(), threadPoolStatusFile);
					}
					//logger.warn(info.toString());
				} catch (Exception e) {
					logger.error("",e);
				}
			}
			
		}
	};
	
	static {
		try {
			new Thread(printer).start();
		} catch (Exception e) {
			logger.error("",e);
		}
	}
    public static ThreadPoolTaskExecutor create(String name, int corePoolSize, int maxPoolSize)
    {
    	return create(name, corePoolSize, maxPoolSize, 10240);
    }
    public static ThreadPoolTaskExecutor create(String key, int corePoolSize, int maxPoolSize,int capacity)
    {
        ThreadPoolTaskExecutor pool = POOLMAP.get(key);
        if ( pool == null )
        {
            synchronized (POOLMAP)
            {
                pool = POOLMAP.get(key);
                if ( pool == null )
                {
                    //logger.warn("@@线程池" + name + "最小线程数目：" + corePoolSize + ",最大线程数目：" + maxPoolSize+",任务队列容量:"+capacity);
                    pool = new ThreadPoolTaskExecutor();
                    //线程池维护的最小线程数，默认最少一个
                    pool.setCorePoolSize(corePoolSize);
                    //线程池维护的最大线程数，默认Integer.MAX_VALUE
                    pool.setMaxPoolSize(maxPoolSize);
                    //线程池空闲时间,默认60秒
                    pool.setKeepAliveSeconds(60);
                    //设置队列的大小，默认Integer.MAX_VALUE
                    pool.setQueueCapacity(capacity);
                    
                    pool.initialize();
                    pool.setThreadGroupName(key);
                    pool.setThreadNamePrefix(key);
                    POOLMAP.put(key, pool);
                }
            }
        }
        return pool;
    }

    public static ThreadPoolTaskExecutor get(String key) {
		return POOLMAP.get(key);
	}
    public static void shutdown()
    {
        for (String key : POOLMAP.keySet())
        {
            shutdown(key);
        }
    }
    
    /**
     * 
     * 描述：关闭并等待指定线程池执行完所有任务
     * @author 陈钦威
     * @created 2017年12月21日 上午10:26:59
     * @since 
     * @return
     */
    public static void shutdown(String key)
    {
    	try {
            ThreadPoolTaskExecutor pool = POOLMAP.get(key);
            if (pool!=null)
            {
                pool.setWaitForTasksToCompleteOnShutdown(false);
                pool.shutdown();
                POOLMAP.remove(key);
                logger.warn("线程池【" + key + "】已关闭......");
            }
        } catch (Exception e) {
			logger.error("",e);
		}
    }
    
	
    
    /**
     * 获取线程池队列任务数
     * @说明: TODO
     * @方法名称: getPoolQueueRunnableSize
     * @参数 @param key
     * @参数 @return
     * @返回类型 Integer    
     * @创建者: 胡常建  
     * @创建时间: 2019年4月23日 下午1:44:21
     * @修改者: 胡常建  
     * @修改时间: 2019年4月23日 下午1:44:21
     */
    public static Integer getPoolQueueRunnableSize(String key)
    {
    	ThreadPoolTaskExecutor poolTaskExecutor= POOLMAP.get(key);
    	if (poolTaskExecutor!=null) {
			return poolTaskExecutor.getThreadPoolExecutor().getQueue().size();
		}else {
			return -1;
		}
    }
    
}
